// 音符数据
const NOTES = {
    C: 0, 'C#': 1, D: 2, 'D#': 3, E: 4, F: 5, 'F#': 6,
    G: 7, 'G#': 8, A: 9, 'A#': 10, B: 11
}
// 调式数据
const KEY_SIGNATURES = {
    'C': { sharps: [], flats: [] },
    'G': { sharps: ['F'], flats: [] },
    'D': { sharps: ['F', 'C'], flats: [] },
    'A': { sharps: ['F', 'C', 'G'], flats: [] },
    'E': { sharps: ['F', 'C', 'G', 'D'], flats: [] },
    'B': { sharps: ['F', 'C', 'G', 'D', 'A'], flats: [] },
    'F#': { sharps: ['F', 'C', 'G', 'D', 'A', 'E'], flats: [] },
    'C#': { sharps: ['F', 'C', 'G', 'D', 'A', 'E' ,'B'], flats: [] },
    'F': { sharps: [], flats: ['B'] },
    'Bb': { sharps: [], flats: ['B', 'E'] },
    'Eb': { sharps: [], flats: ['B', 'E', 'A'] },
    'Ab': { sharps: [], flats: ['B', 'E', 'A', 'D'] },
    'Db': { sharps: [], flats: ['B', 'E', 'A', 'D', 'G'] },
    'Gb': { sharps: [], flats: ['B', 'E', 'A', 'D', 'G', 'C'] },
    'Cb': { sharps: [], flats: ['B', 'E', 'A', 'D', 'G', 'C' ,'F'] },
};

//五线谱相关变量
const baseY0=25
const Staff = document.getElementById('Staff');
const staffX1 = 750, staffX2 = 1250;
const signaturestart = staffX1 + 60
const staffWidth = staffX2 - staffX1;
const ledgerLen = staffWidth / 10;
const ledgerStart = staffX1+200;
const ledgerEnd = ledgerStart + ledgerLen;
const staffgap=15

//音符对照表
const notesinfo = {'A0':{position:baseY0+staffgap/2*45, numero:45}, 'B0':{position:baseY0+staffgap/2*44, numero:44}}
const notesname=['C','D','E','F','G','A','B']
let tempcounter2=1
let tempconuter1=0
for (let numero = 43; numero >=2; numero--){
    notesinfo[notesname[tempconuter1] + tempcounter2.toString()]={position:baseY0+staffgap/2*numero, numero:numero}
    tempconuter1++
    if (tempconuter1 === 7){
        tempconuter1 = 0
        tempcounter2++
    }
}
notesinfo['C7']={position:baseY0+staffgap/2*1, numero:1}

// 全局变量
let currentNote = null;
let isPlaying = false;
let timer = null;
let startTime = null;
let correctCount = 0;
let errorCount = 0;
let isMouseDown = false;
let lastPlayedKey = null;
let currentkeysignature = '';
let currentanswer = '';
let ledgerlines = null;
let rangeStart = document.getElementById('rangeStart').value;
let rangeEnd = document.getElementById('rangeEnd').value;
let entries= Object.entries(notesinfo)
let ranges = entries

// 音名映射
const NOTE_NAMES = {
    C: 'C', 'C#': 'C#', D: 'D', 'D#': 'D#', E: 'E', F: 'F', 'F#': 'F#', G: 'G', 'G#': 'G#', A: 'A', 'A#': 'A#',
    Db: 'Db', Eb: 'Eb', Gb: 'Gb', Ab: 'Ab', Bb: 'Bb'
};
const NUMBER_MAP = {
    C: 1, D: 2, E: 3, F: 4, G: 5, A: 6, B: 7,
    'C#': '1#', 'D#': '2#', 'F#': '4#', 'G#': '5#', 'A#': '6#',
    Db: '2b', Eb: '3b', Gb: '5b', Ab: '6b', Bb: '7b'
};
const SHARP_TO_FLAT = {
    'C#': 'Db', 'D#': 'Eb', 'F#': 'Gb', 'G#': 'Ab', 'A#': 'Bb'
};
const FLAT_TO_SHARP = {
    'Db': 'C#', 'Eb': 'D#', 'Gb': 'F#', 'Ab': 'G#', 'Bb': 'A#'
};

// 播放音符声音
function playNote(note, octave) {
    let fileNote = note;
    if (note.includes('#')) fileNote = SHARP_TO_FLAT[note] || note;
    const audio = new Audio(`notes/${fileNote}${octave}.mp3`);
    audio.play();
}

// 初始化钢琴
function initPiano() {
    const piano = document.getElementById('piano');
    piano.innerHTML = '';
    const whiteKeys = ['C', 'D', 'E', 'F', 'G', 'A', 'B'];
    const blackKeyMap = {
        'C': 'C#',
        'D': 'D#',
        'F': 'F#',
        'G': 'G#',
        'A': 'A#'
    };
    let whiteKeyEls = [];
    let keyIndex = 0;
    // 渲染白键，从A0开始
    for (let octave = 0; octave <= 8; octave++) {
        for (let i = 0; i < whiteKeys.length; i++) {
            // 只保留A0、B0、C1...C8
            if (octave === 0 && i < 5) continue; // 只要A0、B0
            if (octave === 8 && i > 0) continue;
            const note = whiteKeys[i];
            const key = document.createElement('div');
            key.className = 'key white-key';
            key.dataset.note = note;
            key.dataset.octave = octave;
            key.style.left = (keyIndex * 36) + 'px';
            key.style.position = 'absolute';
            key.style.cursor = 'pointer';
            key.style.userSelect = 'none';
            const label = document.createElement('div');
            label.className = 'key-label';
            label.textContent = note + octave;
            label.style.display = 'none'; // 初始隐藏
            key.appendChild(label);
            addKeyPressEffect(key);
            piano.appendChild(key);
            whiteKeyEls.push({el: key, note, octave, index: keyIndex});
            keyIndex++;
        }
    }
    // 渲染黑键
    for (let i = 0; i < whiteKeyEls.length; i++) {
        const {note, octave, el, index} = whiteKeyEls[i];
        if (blackKeyMap[note]) {
            if (octave === 8) continue;
            const blackNote = blackKeyMap[note];
            const blackKey = document.createElement('div');
            blackKey.className = 'key black-key';
            blackKey.dataset.note = blackNote;
            blackKey.dataset.octave = octave;
            blackKey.style.left = (index * 36 + 26) + 'px';
            blackKey.style.cursor = 'pointer';
            blackKey.style.userSelect = 'none';
            const blackLabel = document.createElement('div');
            blackLabel.className = 'key-label';
            blackLabel.textContent = blackNote + octave;
            blackLabel.style.display = 'none'; // 初始隐藏
            blackKey.appendChild(blackLabel);
            addKeyPressEffect(blackKey);
            piano.appendChild(blackKey);
        }
    }
    piano.style.width = (whiteKeyEls.length * 36) + 'px';
}

// 初始化五线谱

function initStaff() {
    //预定义变量
    Staff.innerHTML = '';
    // 高音谱号𝄞
    const gClef = document.createElementNS('http://www.w3.org/2000/svg', 'text');
    gClef.setAttribute('x', staffX1);
    gClef.setAttribute('y', baseY0 + 140);
    gClef.setAttribute('font-size', '80');
    gClef.setAttribute('font-family', 'serif');
    gClef.textContent = '𝄞';
    Staff.appendChild(gClef);
    // 低音谱号𝄢
    const fClef = document.createElementNS('http://www.w3.org/2000/svg', 'text');
    fClef.setAttribute('x', staffX1);
    fClef.setAttribute('y', baseY0 + 235);
    fClef.setAttribute('font-size', '80');
    fClef.setAttribute('font-family', 'serif');
    fClef.textContent = '𝄢';
    Staff.appendChild(fClef);
    //五线谱
    for (let i = 1; i <=22; i++) {
        const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
        
        if ((i >= 1 && i <= 5) || i === 11 || (i >= 17 && i <= 22)){
            line.setAttribute('class', 'ledger-line');
            line.setAttribute('x1', ledgerStart);
            line.setAttribute('y1',  baseY0 + i * staffgap);
            line.setAttribute('x2', ledgerEnd);
            line.setAttribute('y2',  baseY0 + i * staffgap);
            Staff.appendChild(line);
        }
        else{
            line.setAttribute('class', 'staff-line');
            line.setAttribute('x1', staffX1);
            line.setAttribute('y1',  baseY0 + i * staffgap);
            line.setAttribute('x2', staffX2);
            line.setAttribute('y2',  baseY0 + i * staffgap);
            Staff.appendChild(line);
        }  
    }
    ledgerlines = Array.from(document.getElementsByClassName('ledger-line'));
}




// G谱号（高音谱表）
const SHARP_POSITIONS_TREBLE = [notesinfo['F5'].position+7.5, notesinfo['C5'].position+7.5, notesinfo['G5'].position+7.5, notesinfo['D5'].position+7.5, notesinfo['A4'].position+7.5, notesinfo['E5'].position+7.5, notesinfo['B4'].position+7.5]; // F C G D A E B
const FLAT_POSITIONS_TREBLE  = [notesinfo['B4'].position+7.5, notesinfo['E5'].position+7.5, notesinfo['A4'].position+7.5, notesinfo['D5'].position+7.5, notesinfo['G4'].position+7.5,notesinfo['C5'].position+7.5, notesinfo['F4'].position+7.5]; // B E A D G C F
// F谱号（低音谱表）
const SHARP_POSITIONS_BASS = SHARP_POSITIONS_TREBLE.map(tempcounter3 => tempcounter3+82.5)
const FLAT_POSITIONS_BASS = FLAT_POSITIONS_TREBLE.map(tempcounter3 => tempcounter3+105); // B E A D G C F
// 更新调式
function updateKeySignature() {
    const key = document.getElementById('keySignature').value;
    const { sharps, flats } = KEY_SIGNATURES[key];
    currentkeysignature = key
    // 清除旧的调号
    const oldAccidentals = document.querySelectorAll('.accidental');
    oldAccidentals.forEach(acc => acc.remove());
    // 升号
    sharps.forEach((note, i) => {
        const sharp = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        sharp.setAttribute('class', 'accidental');
        sharp.setAttribute('x', signaturestart + i * 14);
        sharp.setAttribute('y', SHARP_POSITIONS_TREBLE[i]);
        
        sharp.textContent = '♯';
        Staff.appendChild(sharp);
        const sharpBass = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        sharpBass.setAttribute('class', 'accidental');
        sharpBass.setAttribute('x', signaturestart + i * 14);
        sharpBass.setAttribute('y', baseY0+SHARP_POSITIONS_BASS[i]);
        sharpBass.textContent = '♯';
        Staff.appendChild(sharpBass);
    });
    // 降号
    flats.forEach((note, i) => {
        const flat = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        flat.setAttribute('class', 'accidental');
        flat.setAttribute('x', signaturestart + i * 18);
        flat.setAttribute('y', FLAT_POSITIONS_TREBLE[i]);
        flat.textContent = '♭';
        Staff.appendChild(flat);
        const flatBass = document.createElementNS('http://www.w3.org/2000/svg', 'text');
        flatBass.setAttribute('class', 'accidental');
        flatBass.setAttribute('x', signaturestart + i * 18);
        flatBass.setAttribute('y', FLAT_POSITIONS_BASS[i]);
        flatBass.textContent = '♭';
        Staff.appendChild(flatBass);
    });
}

function generateRandomNote() {
    // 只从映射表中选取
    return ranges[Math.floor(Math.random() * ranges.length)]
}

function displayNote(a) {
    // 移除旧的音符
    const oldNotes = document.querySelectorAll('.note');
    oldNotes.forEach(note => note.remove());
    ledgerlines.forEach(line => line.style.stroke = 'transparent');
    // 绘制音符
    const noteElement = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    noteElement.setAttribute('class', 'note');
    noteElement.setAttribute('cx', ledgerStart+25);
    noteElement.setAttribute('cy', a[1].position);
    noteElement.setAttribute('r', '7.5');
    //是否增加加线
    if (a[1].numero <= 10){
        for (let i = 0; i <=4; i++)
        {
        if (ledgerlines[i].getAttribute('y1') >= a[1].position){
            ledgerlines[i].style.stroke = '#000';
        }
        }
    }
    if (a[1].numero === notesinfo['C4'].numero){
        ledgerlines[5].style.stroke = '#000';
    }
    if (a[1].numero >= notesinfo['E2'].numero){
        for (let i = 6; i <= 11 ; i++)
        {
        if (ledgerlines[i].getAttribute('y1') <= a[1].position){
            ledgerlines[i].style.stroke = '#000';
        }
        }
    }

    Staff.appendChild(noteElement);
    // 正常键
    if (currentkeysignature === 'C')
        {
            currentanswer = currentNote[0]
        }
    // 正常黑键
    else
    {
        if (KEY_SIGNATURES[currentkeysignature].sharps.includes(currentNote[0][0])){
            currentanswer = currentNote[0][0] + '#' + currentNote[0][1]
        }
        else if (KEY_SIGNATURES[currentkeysignature].flats.includes(currentNote[0][0])){
            currentanswer = currentNote[0][0] + 'b' + currentNote[0][1]
        }
        else{
            currentanswer = currentNote[0] 
        }
    }
    // 特殊键
    if (currentanswer.startsWith('E#')){
        currentanswer = 'F' + currentanswer.slice(2)
    }
    else if (currentanswer.startsWith('B#')){
        currentanswer = 'C' + `${+currentanswer.slice(2) + 1}`
    }
    else if (currentanswer.startsWith('Cb')){
        currentanswer = 'B' + `${+currentanswer.slice(2) - 1}`
    }
    else if (currentanswer.startsWith('Fb')){
        currentanswer = 'E' + currentanswer.slice(2)
    }
    else if (currentanswer.startsWith('Db')){
        currentanswer = 'C#' + currentanswer.slice(2)
    }
    else if (currentanswer.startsWith('Eb')){
        currentanswer = 'D#' + currentanswer.slice(2)
    }
    else if (currentanswer.startsWith('Gb')){
        currentanswer = 'F#' + currentanswer.slice(2)
    }
    else if (currentanswer.startsWith('Ab')){
        currentanswer = 'G#' + currentanswer.slice(2)
    }
    else if (currentanswer.startsWith('Bb')){
        currentanswer = 'A#' + currentanswer.slice(2)
    }

    console.log(currentanswer)
    
    
}

function handleKeyClick(note, octave) {
    // 游戏未开始或没有当前音符
    if (!isPlaying || !currentNote) return;
    if (note + octave === currentanswer) {
        // 正确答案
        showFeedback(true);
        correctCount++;
        currentNote = generateRandomNote();
        displayNote(currentNote);
    } else {
        // 错误答案
        showFeedback(false);
        errorCount++;
    }
    updateStats();
}

// 显示反馈信息
function showFeedback(isCorrect) {
    const feedback = document.getElementById('feedback');
    feedback.textContent = isCorrect ? '恭喜你点对了！' : '你并没有点对';
    feedback.className = `feedback ${isCorrect ? 'correct' : 'incorrect'}`;
    feedback.style.display = 'block';
    if (!isCorrect) {
        feedback.classList.remove('shake');
        // 触发重绘以重置动画
        void feedback.offsetWidth;
        feedback.classList.add('shake');
    }
    setTimeout(() => {
        feedback.style.display = 'none';
    }, 10000);
}

// 更新统计信息
function updateStats() {
    document.getElementById('correctCount').textContent = correctCount;
    document.getElementById('errorCount').textContent = errorCount;
    const accuracy = correctCount + errorCount > 0 
        ? Math.round((correctCount / (correctCount + errorCount)) * 100) 
        : 0;
    document.getElementById('accuracy').textContent = accuracy + '%';
}

// 更新计时器
function updateTimer() {
    if (!isPlaying) return;
    const now = new Date();
    const elapsed = Math.floor((now - startTime) / 1000);
    const hours = Math.floor(elapsed / 3600);
    const minutes = Math.floor((elapsed % 3600) / 60);
    const seconds = elapsed % 60;
    // 始终显示三位
    const timeStr = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    document.getElementById('timer').textContent = timeStr;
}

// 开始/暂停游戏
function toggleGame() {
    const startBtn = document.getElementById('startBtn');
    if (!isPlaying) {
        // 开始游戏
        isPlaying = true;
        startTime = new Date();
        startBtn.textContent = '暂停';
        timer = setInterval(updateTimer, 1000);
        currentNote = generateRandomNote();
        displayNote(currentNote);
    } else {
        // 暂停游戏
        isPlaying = false;
        startBtn.textContent = '开始';
        clearInterval(timer);
    }
}

// 停止游戏
function stopGame() {
    isPlaying = false;
    document.getElementById('startBtn').textContent = '开始';
    clearInterval(timer);
    correctCount = 0;
    errorCount = 0;
    currentNote = null;
    updateStats();
    document.getElementById('timer').textContent = '00:00:00';
    
    // 清除五线谱上的音符
    const oldNotes = document.querySelectorAll('.note');
    oldNotes.forEach(note => note.remove());
    ledgerlines.forEach(line => line.style.stroke = 'transparent');
}



// 更新琴键标签显示
function updateKeyLabels() {
    const showNames = document.getElementById('showSolfege').checked;
    const showNumbers = document.getElementById('showNumbers').checked;
    
    document.querySelectorAll('.key-label').forEach(label => {
        const note = label.parentElement.dataset.note;
        const octave = label.parentElement.dataset.octave;
        // 判断是否黑键

        if (showNames) {
            // 显示音名和八度
            label.textContent = (NOTE_NAMES[note] || note) + octave;
            label.style.display = '';
        } else if (showNumbers) {
            // 白键1-7，黑键1#等
            label.textContent = NUMBER_MAP[note] || '';
            label.style.display = '';
        } else {
            label.style.display = 'none';
        }
    });
}



// 更新黑键标记
function updateBlackKeyLabels() {
    const useFlats = document.getElementById('blackKeyMode').checked;
    const showNumbers = document.getElementById('showNumbers').checked;
    const blackKeys = document.querySelectorAll('.black-key');
    blackKeys.forEach(key => {
        let note = key.dataset.note;
        const octave = key.dataset.octave;
        const label = key.querySelector('.key-label');
        if (useFlats) {
            // 使用降号
            note = SHARP_TO_FLAT[note] || note;
            key.dataset.note = note;
            if (label.style.display !== 'none') {
                if (showNumbers) {
                    label.textContent = NUMBER_MAP[note] || '';
                } else {
                    label.textContent = (NOTE_NAMES[note] || note) + octave;
                }
            }
        } else {
            // 使用升号
            note = FLAT_TO_SHARP[note] || note;
            key.dataset.note = note;
            if (label.style.display !== 'none') {
                if (showNumbers) {
                    label.textContent = NUMBER_MAP[note] || '';
                } else {
                    label.textContent = (NOTE_NAMES[note] || note) + octave;
                }
            }
        }
    });
}

// 修改范围
function modifyRange() {
    rangeStart = document.getElementById('rangeStart').value;
    rangeEnd = document.getElementById('rangeEnd').value;
    console.log(rangeStart,rangeEnd);
    ranges = entries.filter(entry => entry[1].numero <= notesinfo[rangeStart].numero && entry[1].numero >= notesinfo[rangeEnd].numero);
    // 显示提示框
    const tip = document.getElementById('modifyTip');
    tip.style.display = 'inline-block';
    tip.style.animation = 'none';
    // 触发重绘
    void tip.offsetWidth;
    tip.style.animation = 'tipShake 0.5s';
    
    // 2秒后隐藏提示框
    setTimeout(() => {
        tip.style.display = 'none';
    }, 2000);
}

// 添加动画样式
const style = document.createElement('style');
style.textContent = `
    @keyframes tipShake {
        0%, 100% { transform: translateX(0); }
        25% { transform: translateX(-5px); }
        75% { transform: translateX(5px); }
    }
`;
document.head.appendChild(style);

// 初始化事件监听器
function initEventListeners() {
    document.getElementById('startBtn').addEventListener('click', toggleGame);
    document.getElementById('stopBtn').addEventListener('click', stopGame);
    document.getElementById('modifyRange').addEventListener('click', modifyRange);
    document.getElementById('showSolfege').addEventListener('change', updateKeyLabels);
    document.getElementById('showNumbers').addEventListener('change', updateKeyLabels);
    document.getElementById('Dontshow').addEventListener('change', updateKeyLabels);
    document.getElementById('keySignature').addEventListener('change', updateKeySignature);
    document.getElementById('blackKeyMode').addEventListener('change', updateBlackKeyLabels);
    
}

// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
    initPiano();
    initStaff();
    initEventListeners();
    updateKeySignature();
});

// 优化按下反馈动画
function addKeyPressEffect(key) {
    key.addEventListener('mousedown', (e) => {
        isMouseDown = true;
        key.classList.add('active');
        const note = key.dataset.note;
        const octave = key.dataset.octave;
        lastPlayedKey = key;
        playNote(note, octave);
        handleKeyClick(note, octave);
    });

    key.addEventListener('mouseup', () => {
        isMouseDown = false;
        key.classList.remove('active');
        lastPlayedKey = null;
    });

    key.addEventListener('mouseenter', (e) => {
        if (isMouseDown && key !== lastPlayedKey) {
            key.classList.add('active');
            const note = key.dataset.note;
            const octave = key.dataset.octave;
            lastPlayedKey = key;
            playNote(note, octave);
            handleKeyClick(note, octave);
        }
    });

    key.addEventListener('mouseleave', () => {
        key.classList.remove('active');
    });

    // 触摸事件处理
    key.addEventListener('touchstart', (e) => {
        e.preventDefault();
        isMouseDown = true;
        key.classList.add('active');
        const note = key.dataset.note;
        const octave = key.dataset.octave;
        lastPlayedKey = key;
        playNote(note, octave);
        handleKeyClick(note, octave);
    });

    key.addEventListener('touchend', () => {
        isMouseDown = false;
        key.classList.remove('active');
        lastPlayedKey = null;
    });

    key.addEventListener('touchcancel', () => {
        isMouseDown = false;
        key.classList.remove('active');
        lastPlayedKey = null;
    });
}

// 添加全局鼠标事件监听器
document.addEventListener('mouseup', () => {
    isMouseDown = false;
    lastPlayedKey = null;
    document.querySelectorAll('.key').forEach(key => key.classList.remove('active'));
}); 